package cn.elwy.rcp.core.model.ui.tree;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

@SuppressWarnings("unchecked")
public class TreeElement implements ITreeNode, Serializable {

  private static final long serialVersionUID = 1L;
  private static final String DATE_KEY = "TreeElementDateKey";

  protected Object item; // 节点的对象信息

  protected ITreeNode parent; // 父节点
  protected List<ITreeNode> children = new ArrayList<ITreeNode>(); // 子节点
  protected String type;
  protected String[] texts; // 显示的文本
  protected String[] images; // 显示的图标
  protected int start; // 分页起始位置
  protected boolean isDynamic;
  protected Map<String, Object> datas = new LinkedHashMap<String, Object>(); // 节点的对象信息

  protected boolean childrenLoaded; // 子节点是否载入
  protected boolean isChecked; // 是否选中
  protected boolean isAutoLoad; // 自动载入子节点
  protected boolean isRootNode; // 是否根节点
  protected boolean isLeafNode; // 是否叶子节点
  protected boolean isRefreshRoot; // false不刷新根节点，true刷新根节点
  protected boolean isRefresh; // false不刷新当前节点，true刷新当前节点

  public TreeElement(Object item) {
    this(null, item, false);
  }

  public TreeElement(ITreeNode parent, Object item) {
    this(parent, item, false);
  }

  public TreeElement(ITreeNode parent, Object item, boolean isAutoLoad) {
    this.parent = parent;
    this.item = item;
    this.isAutoLoad = isAutoLoad;
    init();
    if (isAutoLoad) {
      load();
    }
  }

  private synchronized final boolean load() {
    if (!childrenLoaded) {
      // try {
      loadChildren();
      childrenLoaded = true;
      // } catch (Exception e) {
      // String errorMsg = "无法加载“" + toString() + "”的子节点：";
      // logger.error(errorMsg, e);
      // RunException error = new RunException(errorMsg + e.getMessage(), e.getCause());
      // MsgDialog.open(null, "错误", error);
      // }
    }
    return childrenLoaded;
  }

  @Override
  public <T> T getData() {
    return (T) datas.get(DATE_KEY);
  }

  @Override
  public <T> T getData(String key) {
    return (T) datas.get(key);
  }

  @Override
  public void setData(String key, Object data) {
    this.datas.put(key, data);
  }

  @Override
  public String getName() {
    return item.toString();
  }

  @Override
  public String getDescription() {
    return toString();
  }

  @Override
  public final List<ITreeNode> getChildrenList() {
    if (!childrenLoaded) {
      load();
    }
    return children;
  }

  @Override
  public ITreeNode[] getChildren() {
    return getChildrenList().toArray(new ITreeNode[] {});
  }

  @Override
  public ITreeNode getParent() {
    return parent;
  }

  @Override
  public void addChildNode(ITreeNode child) {
    if (child instanceof ITreeNode) {
      children.add(child);
      child.setParent(this);
    }
  }

  @Override
  public void setChildren(List<ITreeNode> children) {
    this.children = children;
  }

  @Override
  public void setParent(ITreeNode parent) {
    this.parent = parent;
  }

  @Override
  public Object getAdapter(@SuppressWarnings("rawtypes") Class adapter) {
    return null;
  }

  @Override
  public void insertChild(ITreeNode child, int index) {
    ITreeNode childNode = child;
    if (index > children.size()) {
      children.add(childNode);
    } else {
      children.add(index, childNode);
    }
    childNode.setParent(this);
  }

  @Override
  public void removeChild(ITreeNode child) {
    children.remove(child);
  }

  @Override
  public ITreeNode getRootNode() {
    ITreeNode rootNode = this;
    while (rootNode.getParent() != null) {
      rootNode = rootNode.getParent();
    }
    return rootNode;
  }

  @Override
  public void init() {
  }

  @Override
  public boolean refresh() {
    children.clear();
    childrenLoaded = false;
    return load();
  }

  @Override
  public boolean hasChildren() {
    if (!childrenLoaded && !isLeafNode()) {
      return true;
    }
    return children == null ? false : children.size() > 0;
  }

  @Override
  public boolean isLeafNode() {
    return isLeafNode;
  }

  @Override
  public String[] getTexts() {
    return texts;
  }

  @Override
  public void setTexts(String[] texts) {
    this.texts = texts;
  }

  @Override
  public String getImage() {
    if (images != null && images.length > 0) {
      return images[0];
    }
    return null;
  }

  @Override
  public String[] getImages() {
    return images;
  }

  @Override
  public void setImages(String[] images) {
    this.images = images;
  }

  @Override
  public int getStart() {
    return start;
  }

  @Override
  public void setStart(int start) {
    this.start = start;
  }

  @Override
  public boolean isChecked() {
    return isChecked;
  }

  @Override
  public void setChecked(boolean isChecked) {
    this.isChecked = isChecked;
  }

  @Override
  public boolean equals(Object obj) {
    if (obj instanceof ITreeNode) {
      ITreeNode treeNode = (ITreeNode) obj;
      if (treeNode.getParent() == parent && item.equals(treeNode.getData())) {
        return true;
      }
    }
    return false;
  }

  @Override
  public String toString() {
    if (item instanceof String[]) {
      StringBuffer toString = new StringBuffer();
      if (parent != null) {
        toString.append(parent.toString());
      }
      String[] value = (String[]) item;
      for (int i = 0, j = value.length; i < j; i++) {
        if (toString.length() > 0) {
          toString.append(",");
        }
        toString.append(value[i]);
      }
      return toString.toString();
    } else {
      return item.toString();
    }
  }

  public void loadChildren() {

  }

  @Override
  public boolean isDynamic() {
    return isDynamic;
  }

  @Override
  public void setDynamic(boolean isDynamic) {
    this.isDynamic = isDynamic;
  }

  @Override
  public String getType() {
    return type;
  }

  @Override
  public void setType(String type) {
    this.type = type;
  }

  @Override
  public <T> T getItem() {
    return (T) item;
  }

  @Override
  public void setItem(Object item) {
    this.item = item;
  }

  public void setData(Object data) {
    datas.put(DATE_KEY, data);
  }

  public Map<String, Object> getDatas() {
    return datas;
  }

  public boolean isChildrenLoaded() {
    return childrenLoaded;
  }

  public void setChildrenLoaded(boolean childrenLoaded) {
    this.childrenLoaded = childrenLoaded;
  }

  public boolean isAutoLoad() {
    return isAutoLoad;
  }

  public void setAutoLoad(boolean isAutoLoad) {
    this.isAutoLoad = isAutoLoad;
  }

  public boolean isRootNode() {
    return isRootNode;
  }

  public void setRootNode(boolean isRootNode) {
    this.isRootNode = isRootNode;
  }

  public boolean isRefreshRoot() {
    return isRefreshRoot;
  }

  public void setRefreshRoot(boolean isRefreshRoot) {
    this.isRefreshRoot = isRefreshRoot;
  }

  public boolean isRefresh() {
    return isRefresh;
  }

  public void setRefresh(boolean isRefresh) {
    this.isRefresh = isRefresh;
  }

  public void setLeafNode(boolean isLeafNode) {
    this.isLeafNode = isLeafNode;
  }

}
